import threading
import wx
from main_ui import ProgressPanel

TASK_COMPLETE_EVT_ID = 1
TASK_RUNNING_EVT_ID = 2


class BackgroundProgressThread(threading.Thread):
    
    def __init__(self, parent, etype_done, etype_update, etype_callback, func, args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args
        self._parent = parent
        self.etype_update = etype_update
        self.etype_done = etype_done
        self.etype_callback = etype_callback

        self.exit = False

    def progress(self, progress, message=None):
        evt = BackgroundEvent(self.etype_update, TASK_RUNNING_EVT_ID, "running", progress, message)
        wx.PostEvent(self._parent, evt)
        return self.exit
    
    def stop(self):
        self.exit = True
            
    def run(self):
        #output = ""
        #print self.func, self.args
        #if self.args:
        #if self.callback:
        output = self.func(*self.args, callback=self.progress)
        #else:
        #    output = self.func(callback=self.progress)
        
        evt = BackgroundEvent(self.etype_done, TASK_COMPLETE_EVT_ID, output, 100)
        wx.PostEvent(self._parent, evt)
        
        evt = BackgroundEvent(self.etype_callback, TASK_COMPLETE_EVT_ID, output, 100)
        wx.PostEvent(self._parent, evt)

    
class BackgroundThread(threading.Thread):    
    def __init__(self, parent, etype_done, etype_callback, func, args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args
        self._parent = parent
        self.etype_done = etype_done
        self.etype_callback = etype_callback

        self.exit = False

    def stop(self):
        self.exit = True
            
    def run(self):

        output = self.func(*self.args)
        
        evt = BackgroundEvent(self.etype_done, TASK_COMPLETE_EVT_ID, output, 100)
        wx.PostEvent(self._parent, evt)
        
        evt = BackgroundEvent(self.etype_callback, TASK_COMPLETE_EVT_ID, output, 100)
        wx.PostEvent(self._parent, evt)



##EVT_DB_TASK_COMPLETE = wx.NewId()
#
#myEVT_BG_TASK = wx.NewEventType()
#EVT_BG = wx.PyEventBinder(myEVT_BG_TASK, 1)

class BackgroundEvent(wx.PyCommandEvent):
    def __init__(self, etype, eid, output=None, progress=None, message=None):
        """Init Result Event."""
        
        wx.PyCommandEvent.__init__(self, etype, eid)
        self.SetEventType(etype)
        self.output = output
        self.progress = progress
        self.eid = eid
        self.message = message
    
    def GetOutput(self):
        return self.output

    def GetProgress(self):
        return self.progress

    def GetMessage(self):
        return self.message 
        
    def task_complete(self):
        return (TASK_COMPLETE_EVT_ID == self.eid)

    #def Stopped(self):
        
        

class ProgressPopup(ProgressPanel):
    def __init__(self, parent, event, status_text, ctrl_thread):
        ProgressPanel.__init__(self, parent)
        self.title.SetLabel(status_text)
        self.ctrl_thread = ctrl_thread
    
    def OnUpdate(self, event):
        percentage = event.GetProgress()
        print "status call", percentage
        
        msg = event.GetMessage()
        if msg:
            self.title.SetLabel(msg)
        #self.title.SetLabel(text)
        self.progress_gauge.SetValue(percentage)
        
    def OnFinished(self,event):
        print "in Onfinished"
        self.Destroy()
        event.Skip()
    
    def OnCancel(self, event): 
        print "cancel background thread"
        self.ctrl_thread.stop()
        #threading.Thread.
        #self.Destroy()
        
#
#def run_in_thread_with_progressbar(func, args, callback, host_gui_object, etype_done):
##    etype_done = wx.NewEventType()
#    done_event = wx.PyEventBinder(etype_done, 1)
#    
#    etype_update= wx.NewEventType()
#    update_event = wx.PyEventBinder(etype_update, 1)
#
#    popup = ProgressPopup(host_gui_object, update_event, "Processing")
#    
#    
#    host_gui_object.Bind(update_event, popup.OnUpdate)
#    
#    host_gui_object.Bind(done_event, callback)
#    host_gui_object.Bind(done_event, popup.OnFinished)
#    
#    new_thread = BackgroundProgressThread(host_gui_object, etype_done, etype_update, func, args)
#    
#    
#    new_thread.start()
#    popup.Show()


def run_in_thread_with_progressbar(func, args, callback, host_gui_object, msg):
    print "visitor function", func
    
    new_thread = None
    etype_done = wx.NewEventType()
    done_event = wx.PyEventBinder(etype_done, 1)
    
    etype_callback = wx.NewEventType()
    callback_event = wx.PyEventBinder(etype_callback, 1)
    
    etype_update= wx.NewEventType()
    update_event = wx.PyEventBinder(etype_update, 1)

    new_thread = BackgroundProgressThread(host_gui_object, etype_done, etype_update, etype_callback, func, args)
    
    popup = ProgressPopup(host_gui_object, update_event, msg, ctrl_thread=new_thread)
    
    host_gui_object.Bind(update_event, popup.OnUpdate)
    if callback:
        host_gui_object.Bind(callback_event, callback)
    
    host_gui_object.Bind(done_event, popup.OnFinished)
        
    new_thread.start()
    popup.Show()
    #popup.SetFocus()
    
    return new_thread
    
    
def run_in_thread(func, args, callback, host_gui_object):
    print "visitor function", func
    
    new_thread = None
    etype_done = wx.NewEventType()
    done_event = wx.PyEventBinder(etype_done, 1)
    
    etype_callback = wx.NewEventType()
    callback_event = wx.PyEventBinder(etype_callback, 1)
    
    new_thread = BackgroundThread(host_gui_object, etype_done, etype_callback, func, args)
    
    if callback:
        host_gui_object.Bind(callback_event, callback)
        
    new_thread.start()
    
    return new_thread

    
def mycount(arg, callback):
    import time 
    for i in range(20):
        time.sleep(1)
        callback(int(i/20.0*100))

def mycount2(arg):
    import time 
    for i in range(20):
        time.sleep(1)
        #callback(int(i/20.0*100))


def done():
    print done
    
def progress_test():
    
    app = wx.App(False)  # Create a new app, don't redirect stdout/stderr to a window.
    frame = wx.Frame(None, wx.ID_ANY, "Hello World")
    
    run_in_thread(mycount2, None, done, frame)
    
    frame.Show()
    app.MainLoop()
    
#progress_test()
